/**************************************************************/
/*********************** 文件处理相关 **************************/
/**************************************************************/

const fs = require("fs");
const path = require("path");
const { N, consoleLog, needParam } = require("./base");
const { aliasPathMap } = require("./const");

/**
 * 判断是否是绝对路径
 * @param {string} pathStr 路径
 * @returns {boolean} 是否是绝对路径
 */
function isAbsPath(pathStr = needParam()) {
  if (!pathStr) return false;
  // 正则表达式匹配Windows风格的绝对路径，如"C:\path\to\file"
  const windowsReg = /^[A-Za-z]:\\[^?<>:"*|]+$/;
  // 正则表达式匹配UNIX风格的绝对路径，如"/path/to/file"
  // const unixReg = /^\/[^?<>:"*|]+$/;
  return windowsReg.test(path); // || unixReg.test(path);
  // return path.isAbsolute(pathStr);
}

/**
 * 获取完整路径（绝对路径）
 * @param {string} pathStr 绝对或相对路径
 * @returns {string} 绝对路径
 */
function getFullPath(pathStr = needParam()) {
  const isAbs = isAbsPath(pathStr);
  const isUseAlias = isAbs ? false : pathStr.charAt(0) !== "/"; // 是否使用了别名
  if (isUseAlias) {
    const alia = pathStr.split("/")[0];
    const realPath = aliasPathMap[alia];
    if (!realPath) throw new Error(`未找到该别名：${alia}`);
    pathStr = pathStr.replace(new RegExp(alia), realPath);
  }
  return isAbs ? pathStr : path.join(process.cwd(), pathStr);
}

/**
 * 递归创建目录(同步方法)
 * 注：nodejs不能一次性创建多层目录，需要递归处理
 * @param dirname 多层目录路径 示例： hello/a/b/c
 * @returns
 */
//  function mkdirsSync(dirname, recursive = true) {
//   fs.mkdirSync(dirname, { recursive });
// }
function mkdirsSync(dirPath) {
  // const fullPath = getFullPath(dirPath);
  if (fs.existsSync(dirPath)) return true;
  if (mkdirsSync(path.dirname(dirPath))) {
    fs.mkdirSync(dirPath);
    return true;
  }
}

/**
 * 递归删除目录(同步方法)
 * 注：nodejs不能一次性删除多层目录，需要递归处理
 * @param dirPath 多层目录路径 示例： hello/a/b/c
 * @param isDelSelf 是否删除自身文件夹，及目录路径的最后一级为空文件夹时，是否删除
 */
function deleteFolderSync(dirPath = "", isDelSelf = true) {
  const fullPath = getFullPath(dirPath);
  if (!fs.existsSync(fullPath)) return;
  fs.readdirSync(fullPath).forEach(file => {
    const curPath = path.join(fullPath, file);
    const isDir = fs.lstatSync(curPath).isDirectory();
    // 如果是文件夹则递归删除
    if (isDir) return deleteFolderSync(curPath, true);
    // 如果是文件则直接删除
    return fs.unlinkSync(curPath);
  });
  isDelSelf && fs.rmdirSync(fullPath); // 删除空文件夹
}

/**
 * 写入文件
 * @param writePath string
 * @param writeStr string 写入的文件内容
 * @param encoding 编码格式
 * @return error 错误信息，如果没有错误，则为null
 */
function writeFileSync(writePath, writeStr, showSuccess = true, encoding = "utf-8") {
  const fullPath = getFullPath(writePath);
  const basename = path.basename(fullPath);
  const isSuccess = mkdirsSync(fullPath.replace(basename, ""));
  if (!isSuccess) {
    consoleLog("创建文件目录失败", "danger");
    return { err: "创建文件目录失败" };
  }
  const err = fs.writeFileSync(fullPath, writeStr, encoding);
  if (err) {
    consoleLog(`写入失败：${fullPath}`, "danger", err);
    return error;
  }
  showSuccess && consoleLog(`写入成功：${fullPath}`);
}

/**
 * 往文件中固定的行写入数据，但不执行写入文件操作（同步）
 * @param file string 文件路径或文件数据
 * @param aimStr string 指定行的字符串，在其后添加一行
 * @param isFile boolean 是否是文件
 * @return 返回添加行数据之后的文件数据字符串
 */
function addToFileLineSync(file = "", aimStr = "", addLines = [], isFile = false) {
  const splitReg = /\r\n|\n|\r/gm;
  const fileStr = isFile ? fs.readFileSync(getFullPath(file), "utf8") : file;
  const lines = fileStr.split(splitReg);
  let ind = lines.findIndex(it => it.replace(/ +/g, "").includes(aimStr)) + 1;
  if (ind === -1) ind = lines.length - 1;
  lines.splice(ind, 0, ...addLines);
  return lines.join(N);
}

module.exports = {
  isAbsPath,
  getFullPath,
  mkdirsSync,
  deleteFolderSync,
  writeFileSync,
  addToFileLineSync,
};
